﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using QuadRemote.Core;

namespace QuadRemote
{
    public class MonitorFrame : GroupBox
    {
        private Int32 monitoringTime;
        private Int32 monitoringTaskQuad;
        private Int32 monitoringTaskSD;
        private Int32 monitoringTaskRN;
        private Int32 monitoringTaskStab;
        private Int32 monitoringSensorIMU;
        private Int32 monitoringSensorIMUError;
        private Int32 monitoringSensorMagn;
        private Int32 monitoringSensorMagnError;
        private Int32 monitoringSensorBaro;
        private Int32 monitoringSensorBaroError;
        private Int32 monitoringSDFreeSectors;
        private Int32 monitoringSDTotalSectors;
        private Int32 monitoringSDWrittenSectors;

        private Int32 omonitoringTime;
        private Int32 omonitoringTaskQuad;
        private Int32 omonitoringTaskSD;
        private Int32 omonitoringTaskRN;
        private Int32 omonitoringTaskStab;
        private Int32 omonitoringSensorIMU;
        private Int32 omonitoringSensorIMUError;
        private Int32 omonitoringSensorMagn;
        private Int32 omonitoringSensorMagnError;
        private Int32 omonitoringSensorBaro;
        private Int32 omonitoringSensorBaroError;
        private Int32 omonitoringSDFreeSectors;
        private Int32 omonitoringSDTotalSectors;
        private Int32 omonitoringSDWrittenSectors;
        private Int32 monitoringBenchIdle;

        private Label lblTime;
        private Label lblTaskQuad;
        private Label lblTaskSD;
        private Label lblTaskRN;
        private Label lblTaskStab;
        private Label lblSensorIMU;
        private Label lblSensorIMUError;
        private Label lblSensorMagn;
        private Label lblSensorMagnError;
        private Label lblSensorBaro;
        private Label lblSensorBaroError;
        private Label lblSDStatus;
        private Label lblSDStatus2;
        private Label lblBenchIdle;

        public MonitorFrame() 
        {
            Text = "Monitor";


            int x1, x2, x3, y;
            int h = 20;
            x1 = 10;
            x2 = 120;
            x3 = 230;
            y = 20;

            ComboBox monitor = new ComboBox();
            monitor.Items.Add("Off");
            monitor.SelectedIndex = 0;
            monitor.Items.Add("1 hz");
            monitor.Items.Add("2 hz");
            monitor.Items.Add("5 hz");
            monitor.Items.Add("10 hz");
            monitor.Items.Add("20 hz");
            monitor.Items.Add("50 hz");
            monitor.Items.Add("100 hz");
            monitor.DropDownStyle = ComboBoxStyle.DropDownList;
            monitor.SelectedIndexChanged += new EventHandler(MonitorClick);
            monitor.Location = new Point(x1, y);
            monitor.Size = new Size(x3+80, 25);
            Controls.Add(monitor);

            y += (int)(h * 1.5f);

            createLabel("Freq", x2, y, true, ContentAlignment.MiddleRight);
            createLabel("Errors", x3, y, true, ContentAlignment.MiddleRight);

            y += h;
            createLabel("Task Quad", x1, y, true, ContentAlignment.MiddleLeft);
            lblTaskQuad = createLabel("...", x2, y, false, ContentAlignment.MiddleRight);
            y += h;
            createLabel("Task SD", x1, y, true, ContentAlignment.MiddleLeft);
            lblTaskSD = createLabel("...", x2, y, false, ContentAlignment.MiddleRight);
            y += h;
            createLabel("Task BT", x1, y, true, ContentAlignment.MiddleLeft);
            lblTaskRN = createLabel("...", x2, y, false, ContentAlignment.MiddleRight);
            y += h;
            createLabel("Task Stab", x1, y, true, ContentAlignment.MiddleLeft);
            lblTaskStab = createLabel("...", x2, y, false, ContentAlignment.MiddleRight);
            y += (int)(h * 1.5f);
            createLabel("Acc / Gyro", x1, y, true, ContentAlignment.MiddleLeft);
            lblSensorIMU = createLabel("...", x2, y, false, ContentAlignment.MiddleRight);
            lblSensorIMUError = createLabel("...", x3, y, false, ContentAlignment.MiddleRight);
            y += h;
            createLabel("Magneto", x1, y, true, ContentAlignment.MiddleLeft);
            lblSensorMagn = createLabel("...", x2, y, false, ContentAlignment.MiddleRight);
            lblSensorMagnError = createLabel("...", x3, y, false, ContentAlignment.MiddleRight);
            y += h;
            createLabel("Baro", x1, y, true, ContentAlignment.MiddleLeft);
            lblSensorBaro = createLabel("...", x2, y, false, ContentAlignment.MiddleRight);
            lblSensorBaroError = createLabel("...", x3, y, false, ContentAlignment.MiddleRight);
            y += (int)(h * 1.5f);
            createLabel("Time since start", x1, y, true, ContentAlignment.MiddleLeft);
            lblTime = createLabel("", x2, y, false, ContentAlignment.MiddleRight);
            
            y += (int)(h * 1.5f);
            
            createLabel("SD Storage", x1, y, true, ContentAlignment.MiddleLeft);
            lblSDStatus = createLabel("...", x2, y, false, ContentAlignment.MiddleLeft);
            lblSDStatus.Width *= 2;
            y += h;
            lblSDStatus2 = createLabel("", x2, y, false, ContentAlignment.MiddleLeft);
            lblSDStatus2.Width *= 2;
            y += (int)(h * 1.5f);
            createLabel("Bench idle++", x1, y, true, ContentAlignment.MiddleLeft);
            lblBenchIdle = createLabel("...", x2, y, false, ContentAlignment.MiddleLeft);

            y += h;

            Bluetooth.instance().commandParsers[(int)CommandId.CMD_MONITORING_SEND] = incomingMonitoringPacket;

            Size = new Size(x3 + 110, y + h);
        }

        private Label createLabel(String text, int x, int y, Boolean bold, System.Drawing.ContentAlignment align)
        {
            Label l = new Label();
            l.Size = new System.Drawing.Size(100, 23);
            l.Location = new System.Drawing.Point(x, y);
            l.Text = text;
            l.Font = Tools.getPrimaryFont();
            l.TextAlign = align;

            if (bold)
            {
                l.Font = new System.Drawing.Font(Tools.getPrimaryFont(), System.Drawing.FontStyle.Bold);
            }
            else
            {
                l.Font = Tools.getPrimaryFont();
            }
            Controls.Add(l);
            return l;
        }

        private delegate void packetEventDelegate(CommandIn args);

        private void MonitorClick(object sender, EventArgs args)
        {
            ComboBox cb = (ComboBox)sender;
            int i;
            Console.WriteLine(cb.Text);
            try
            {
                string[] str = cb.Text.Split(new string[]{" "},StringSplitOptions.None);
                i = Int32.Parse(str[0]);
            }
            catch (Exception e)
            {
                i = 0;
            }
            Console.WriteLine("Monitoring " + i);

            new CommandOut(CommandId.CMD_MONITORING_SET, (byte)(i >> 8), (byte)(i & 0xFF));
        }

        private void incomingMonitoringPacket(CommandIn args)
        {
            if (lblTime.InvokeRequired)
            {
                this.Invoke(new packetEventDelegate(incomingMonitoringPacket), new object[] { args });
                return;
            }
            //02-81-54-49-4D-45-00-01-00-00-38-D6-54-5F-51-55-41-44-00-01-00-00-03-C2-54-5F-53-44-00-01-00-00-00-00-54-5F-52-4E-00-01-00-00-00-00-54-5F-53-54-41-42-00-01-00-00-00-00-53-5F-4D-41-47-4E-00-01-00-00-02-E4-01-00-00-00-00-53-5F-49-4D-55-00-01-00-00-26-3F-01-00-00-00-00-53-5F-42-41-52-4F-00-01-00-00-00-F4-01-00-00-00-00-53-44-5F-53-54-41-54-55-53-00-01-00-00-00-00-01-00-3B-50-00-01-00-00-00-00
            int i;
            String s = "";
            int l = 0;


            omonitoringTime = monitoringTime;
            omonitoringTaskQuad = monitoringTaskQuad;
            omonitoringTaskSD = monitoringTaskSD;
            omonitoringTaskRN = monitoringTaskRN;
            omonitoringTaskStab = monitoringTaskStab;
            omonitoringSensorIMU = monitoringSensorIMU;
            omonitoringSensorIMUError = monitoringSensorIMUError;
            omonitoringSensorMagn = monitoringSensorMagn;
            omonitoringSensorMagnError = monitoringSensorMagnError;
            omonitoringSensorBaro = monitoringSensorBaro;
            omonitoringSensorBaroError = monitoringSensorBaroError;
            omonitoringSDFreeSectors = monitoringSDFreeSectors;
            omonitoringSDTotalSectors = monitoringSDTotalSectors;
            omonitoringSDWrittenSectors = monitoringSDWrittenSectors;

            for (i = 0; i < args.packet.Length; i++)
            {
                if (args.packet[i] == 0x01)
                {
                    int k = Tools.bytesToInt32(args.packet, i + 1);
                    //Console.WriteLine(s);
                    if (s.Equals("TIME")) monitoringTime = k;
                    else if (s.Equals("T_QUAD")) monitoringTaskQuad = k;
                    else if (s.Equals("T_SD")) monitoringTaskSD = k;
                    else if (s.Equals("T_RN")) monitoringTaskRN = k;
                    else if (s.Equals("T_STAB")) monitoringTaskStab = k;
                    else if (s.Equals("S_MAGN") && l == 0) monitoringSensorMagn = k;
                    else if (s.Equals("S_MAGN") && l == 1) monitoringSensorMagnError = k;
                    else if (s.Equals("S_IMU") && l == 0) monitoringSensorIMU = k;
                    else if (s.Equals("S_IMU") && l == 1) monitoringSensorIMUError = k;
                    else if (s.Equals("S_BARO") && l == 0) monitoringSensorBaro = k;
                    else if (s.Equals("S_BARO") && l == 1) monitoringSensorBaroError = k;
                    else if (s.Equals("SD_STATUS") && l == 0) monitoringSDFreeSectors = k;
                    else if (s.Equals("SD_STATUS") && l == 1) monitoringSDTotalSectors = k;
                    else if (s.Equals("SD_STATUS") && l == 2) monitoringSDWrittenSectors = k;
                    else if (s.Equals("_BENCH")) monitoringBenchIdle = k;
                    l++;
                    i += 4;
                }
                else
                {
                    s = "";
                    l = 0;
                    while (args.packet[i] != 0x00)
                    {
                        s += System.Text.Encoding.ASCII.GetString(args.packet, i, 1);
                        i++;
                    }
                }
            }

            float diff = (monitoringTime - omonitoringTime) / 1000.0f;

            int t = monitoringTime;
            int minutes = t / 1000 / 60;
            t -= minutes * 1000 * 60;
            int seconds = t / 1000;
            t -= seconds * 1000;
            int microseconds = t;

            lblTime.Text = minutes + ":" + (seconds < 10 ? "0" : "") + seconds + "." + (microseconds < 10 ? "00" : microseconds < 100 ? "0" : "") + microseconds;
            if (diff != 0)
            {
                lblTaskQuad.Text = ((float)(monitoringTaskQuad - omonitoringTaskQuad) / diff).ToString() + " hz";
                lblTaskSD.Text = ((float)(monitoringTaskSD - omonitoringTaskSD) / diff).ToString() + " hz";
                lblTaskRN.Text = ((float)(monitoringTaskRN - omonitoringTaskRN) / diff).ToString() + " hz";
                lblTaskStab.Text = ((float)(monitoringTaskStab - omonitoringTaskStab) / diff).ToString() + " hz";

                lblSensorIMU.Text = ((float)(monitoringSensorIMU - omonitoringSensorIMU) / diff).ToString() + " hz";
                lblSensorMagn.Text = ((float)(monitoringSensorMagn - omonitoringSensorMagn) / diff).ToString() + " hz";
                lblSensorBaro.Text = ((float)(monitoringSensorBaro - omonitoringSensorBaro) / diff).ToString() + " hz";

                lblSensorIMUError.Text = monitoringSensorIMUError + "x";
                lblSensorMagnError.Text = monitoringSensorMagnError + "x";
                lblSensorBaroError.Text = monitoringSensorBaroError + "x";

                lblSDStatus.Text = ((long)(monitoringSDTotalSectors - monitoringSDFreeSectors) * 512 / 1024 / 1024) + " mb / " + ((long)monitoringSDTotalSectors * 512 / 1024 / 1024);
                lblSDStatus2.Text = "Written: " + ((long)monitoringSDWrittenSectors / 2) + " kb (" + (((long)monitoringSDWrittenSectors - (long)omonitoringSDWrittenSectors) / diff / 2) + " kb/sec)";
            }
            lblBenchIdle.Text = monitoringBenchIdle + "";
        }
    }
}
